home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / mach / amiga / scsi9091.lzh / unit.c < prev   
Encoding:
C/C++ Source or Header  |  1991-02-24  |  6.7 KB  |  242 lines

  1. #include <exec/types.h>
  2. #include <exec/nodes.h>
  3. #include <exec/resident.h>
  4. #include <exec/errors.h>
  5. #include <libraries/expansionbase.h>
  6. #include <libraries/configvars.h>
  7. #include <devices/trackdisk.h>
  8.  
  9. /*
  10.  * Set SysBase to a local variable, that loads directly from 4 when it
  11.  * has to be reloaded
  12.  */
  13. #define BASE_EXT_DECL
  14. #define BASE_NAME (*(void **)4)
  15. #include <inline/exec.h>
  16.  
  17. #include "device.h"
  18.  
  19. /*
  20.  * Unit task. First figures out, of which type it is, then waits for
  21.  * command requests from BeginIO.
  22.  */
  23.  
  24. DECL_DPRINTF;
  25. extern struct MsgPort *CreatePort(char *name, int pri);
  26.  
  27. extern int (*cmd_table[]) ();
  28.  
  29. /* this is a unit task */
  30.  
  31. void
  32. unit_start (struct scsi_unit *su)
  33. {
  34.   struct scsi_msg *sm = &su->scu_hmessage;
  35.   struct SCSICmd *cmd;
  36.   struct IOStdReq *io_req;
  37.   ubyte *cb;
  38.   ulong inq_buf;
  39.   ulong sense_buf;
  40.   struct MsgPort *mp;
  41.   int retries;
  42.   
  43. DPRINTF(("unit-task: %ld started", su->scu_unitnum));
  44.  
  45.   mp = &su->scu_unit.unit_MsgPort;
  46.   mp->mp_Node.ln_Type = NT_MSGPORT;
  47.   mp->mp_SigBit = AllocSignal(-1);
  48.   mp->mp_SigTask = FindTask(0);
  49.   mp->mp_Flags = PA_SIGNAL;
  50.   NewList(&mp->mp_MsgList);
  51.  
  52.   sm->scm_message.mn_ReplyPort = mp;
  53.  
  54.   su->scu_cmd_mp = CreatePort(0,0);
  55.   su->scu_errors = su->scu_errorlevel = 0;
  56.  
  57.   sm->scm_unit = su->scu_unitnum;
  58.   cmd = &su->scu_scsicmd;
  59.  
  60.   sm->scm_scsi_cmd = cmd;
  61.   cmd->scsi_Command = cb = su->scu_cmd;
  62.   
  63.   /* first find out, what kind this device is of */
  64.   cb[0] = 0x12; /* INQUIRY */
  65.   cb[1] = cb[2] = cb[3] = 0;
  66.   cb[4] = 2; /* allocation length */
  67.   cb[5] = 0;
  68.   cmd->scsi_Data = (UWORD *)&inq_buf;
  69.   cmd->scsi_Length = 2;
  70.   cmd->scsi_Flags = SCSIF_READ|SCSIF_OLDAUTOSENSE;
  71.   cmd->scsi_SenseData = (UBYTE *)&sense_buf;
  72.   cmd->scsi_SenseLength = 4;
  73.   retries = 60;
  74.  
  75.   /* account for UNIT ATTENTION sense response */
  76.   do
  77.     {
  78.       sm->scm_cmd = SCM_CMD_EXEC_SCSI;
  79.       
  80.       PutGetMsg(su->scu_hmsgport, &su->scu_unit.unit_MsgPort, 
  81.         (struct Message *)sm);
  82.     }
  83.   /* as long as the device responds UNIT_ATTENTION */
  84.   while (((sm->scm_cmd == HFERR_BadStatus && sense_buf == 0x07000600)
  85.       || (sm->scm_cmd > HFERR_BadStatus)) && retries-- > 0);
  86.  
  87. DPRINTF(("identified unit %ld, result = %ld, inq_buf = $%lx, sense = $%lx",
  88.      su->scu_unitnum, sm->scm_cmd, inq_buf, sense_buf));
  89.   
  90.   if (sm->scm_cmd == 0) /* scm_cmd is io_Error when returned */
  91.     {
  92.       su->scu_type = inq_buf >> 24;
  93.       if (inq_buf & 0x00800000) su->scu_type |= SCU_TYPE_RMB;
  94.     }
  95.   else
  96.     {
  97.       /* in that case assume a non removable DIRECT ACCESS device... */
  98.       su->scu_type = SCU_TYPE_DIRECT;
  99.     }
  100.  
  101.   /* START/STOP unit on sequential devices means LOAD/UNLOAD, since
  102.    * we can't garantee that there's a tape inserted, this command might
  103.    * always fail... so better don't issue it */
  104.  
  105.   if ((su->scu_type & ~SCU_TYPE_RMB) == SCU_TYPE_DIRECT)
  106.     {
  107.       cb[0] = 0x1b; /* START/STOP UNIT */
  108.       cb[1] = 0; /* not immed, return, when unit really ready */
  109.       cb[2] = cb[3] = 0;
  110.       cb[4] = 1; /* start unit */
  111.       cb[5] = 0;
  112.       cmd->scsi_Data = 0;
  113.       cmd->scsi_Length = 0;
  114.       
  115.       for (retries = 0; retries < 60; retries ++)
  116.         {
  117.           sm->scm_cmd = SCM_CMD_EXEC_SCSI;
  118.           
  119.           PutGetMsg(su->scu_hmsgport, &su->scu_unit.unit_MsgPort, 
  120.                 (struct Message *)sm);
  121.           if (sm->scm_cmd == 0) break;
  122.         }
  123.  
  124. DPRINTF(("unit %ld, start_unit returned %ld, retry = %ld",
  125.      su->scu_unitnum, sm->scm_cmd, retries));
  126.     }
  127.  
  128.   /* now set block length.. this is important for streamers or other
  129.    * devices that may support different block lengths */
  130.   if ((su->scu_type & ~SCU_TYPE_RMB) == SCU_TYPE_DIRECT)
  131.     {
  132.       cb[0] = 0x15; /* MODE_SELECT */
  133.       cb[1] = 1; /* save parameters */
  134.       cb[2] = cb[3] = 0;
  135.       cb[4] = 12; /* parameter list length */
  136.       cb[5] = 0;
  137.       /* this is the actual parameter list, that switches the device into
  138.        * 512 byte block mode */
  139.       su->scu_buf[0] = 
  140.       su->scu_buf[1] =
  141.       su->scu_buf[2] = 0;
  142.       su->scu_buf[3] = 8;
  143.       su->scu_buf[4] =
  144.       su->scu_buf[5] =
  145.       su->scu_buf[6] =
  146.       su->scu_buf[7] =
  147.       su->scu_buf[8] =
  148.       su->scu_buf[9] = 0;
  149.       su->scu_buf[10] = 2; /* 0x200 = 512 */
  150.       su->scu_buf[11] = 0;
  151.     }
  152.   else /* SCU_TYPE_SEQUENTIAL */
  153.     {
  154.       cb[0] = 0x15; /* MODE_SELECT */
  155.       cb[1] = 0; /* reserved */
  156.       cb[2] = cb[3] = 0;
  157.       cb[4] = 12; /* parameter list length */
  158.       cb[5] = 0;
  159.       /* this is the actual parameter list, that switches the device into
  160.        * 512 byte block mode */
  161.       su->scu_buf[0] = 
  162.       su->scu_buf[1] = 0; /* reserved */
  163.       su->scu_buf[2] = 0x10; /* buffered writes ok, default speed */
  164.       su->scu_buf[3] = 8;
  165.       su->scu_buf[4] =    /* default density */
  166.       su->scu_buf[5] =
  167.       su->scu_buf[6] =
  168.       su->scu_buf[7] =
  169.       su->scu_buf[8] =
  170.       su->scu_buf[9] = 0;
  171.       su->scu_buf[10] = 2; /* 0x200 = 512 */
  172.       su->scu_buf[11] = 0;
  173.    }
  174.  
  175.   cmd->scsi_Data = (UWORD *)su->scu_buf;
  176.   cmd->scsi_Flags = SCSIF_OLDAUTOSENSE; /* no READ, this is a write ! */
  177.   cmd->scsi_Length = 12;
  178.  
  179.   for (retries = 0; retries < 60; retries ++)
  180.     {
  181.       sm->scm_cmd = SCM_CMD_EXEC_SCSI;
  182.       
  183.       PutGetMsg(su->scu_hmsgport, &su->scu_unit.unit_MsgPort, 
  184.         (struct Message *)sm);
  185.       if (sm->scm_cmd == 0) break;
  186.     }
  187.  
  188. DPRINTF(("unit %ld, mode_select returned %ld, retry = %ld",
  189.      su->scu_unitnum, sm->scm_cmd, retries));
  190.   
  191.  
  192.   /* reading the first cylinder, until we don't get any errors, seems
  193.    * a good way to ensure, that the unit is working.. well, hddisk
  194.    * does it that way... */
  195.  
  196.   if ((su->scu_type & ~SCU_TYPE_RMB) == SCU_TYPE_DIRECT)
  197.     {
  198.       cb[0] = 0x8; /* READ */
  199.       cb[1] = cb[2] = cb[3] = 0;
  200.       cb[4] = 1; /* allocation length (1 Block)*/
  201.       cb[5] = 0;
  202.       cmd->scsi_Length = 512;
  203.       cmd->scsi_Data = (UWORD *)su->scu_buf;
  204.       cmd->scsi_Flags = SCSIF_READ|SCSIF_OLDAUTOSENSE;
  205.  
  206.       for (retries = 0; retries < 60; retries ++)
  207.     {
  208.       sm->scm_cmd = SCM_CMD_EXEC_SCSI;
  209.       
  210.       PutGetMsg(su->scu_hmsgport, &su->scu_unit.unit_MsgPort, 
  211.             (struct Message *)sm);
  212.       if (sm->scm_cmd == 0) break;
  213.     }
  214.     }
  215.   
  216.   /* for now, DON'T mount the disk.. we can do this manually, and this
  217.    * garantees yet another source of bugs we can eliminate during the
  218.    * testing phase.. */
  219.  
  220. DPRINTF(("unit %ld ready, type $%lx, (retries = %ld), awaiting commands",
  221.      su->scu_unitnum, su->scu_type, retries));
  222.  
  223. #ifdef ENABLE_CACHE
  224.   invalidate_cache (su);
  225. #endif
  226.  
  227.   for (;;)  
  228.     {
  229.       WaitPort(su->scu_cmd_mp);
  230.       while (io_req = (struct IOStdReq *)GetMsg(su->scu_cmd_mp))
  231.     {
  232. DPRINTF(("unit %ld (%ld), command %ld",
  233.      su->scu_unitnum, ((struct scsi_unit*)io_req->io_Unit)->scu_unitnum,
  234.      io_req->io_Command));
  235.  
  236.       /* beginio already validated the io_Command field */          
  237.       io_req->io_Error = (*cmd_table[io_req->io_Command])(io_req);
  238.       ReplyMsg((struct Message *)io_req);
  239.         }
  240.     }
  241. }
  242.